package cuongnh.project.japanesediary.vocabulary.ui.editor.grammar.page.related.section;

import java.util.Set;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import cuongnh.project.japanesediary.vocabulary.application.Activator;
import cuongnh.project.japanesediary.vocabulary.common.CommonServices;
import cuongnh.project.japanesediary.vocabulary.common.CommonUtils;
import cuongnh.project.japanesediary.vocabulary.model.Grammar;
import cuongnh.project.japanesediary.vocabulary.ui.dialog.AddRelatedGrammarDialog;

public class AntonymGrammarsSection extends SectionPart {
	private DataBindingContext m_bindingContext;
	private Grammar grammar;
	private CommonServices commonServices;
	private TableViewer tblAntonymGrammars;

	/**
	 * Create the SectionPart.
	 * 
	 * @param parent
	 * @param toolkit
	 * @param style
	 */
	public AntonymGrammarsSection(Composite parent, FormToolkit toolkit,
			int style, Grammar grammar, CommonServices commonServices) {
		super(parent, toolkit, style);
		this.grammar = grammar;
		this.commonServices = commonServices;
		createClient(getSection(), toolkit);
	}

	private void initData() {
		grammar = commonServices.getGrammarDao().getGrammarWithAntonyms(
				grammar.getGrammarId());
	}

	/**
	 * Fill the section.
	 */
	private void createClient(Section section, FormToolkit toolkit) {
		section.setText("Antonum Vocabularies");
		Composite container = toolkit.createComposite(section);
		section.setClient(container);
		toolkit.paintBordersFor(container);
		createToolBar(section);

		Composite compRelatedGrammar = new Composite(section, SWT.NONE);
		toolkit.adapt(compRelatedGrammar);
		toolkit.paintBordersFor(compRelatedGrammar);
		section.setClient(compRelatedGrammar);

		tblAntonymGrammars = new TableViewer(compRelatedGrammar, SWT.BORDER
				| SWT.FULL_SELECTION | SWT.MULTI);
		Table table = tblAntonymGrammars.getTable();
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		tblAntonymGrammars.getTable().setLinesVisible(true);
		tblAntonymGrammars.getTable().setHeaderVisible(true);

		TableViewerColumn tbclvGrammar = new TableViewerColumn(
				tblAntonymGrammars, SWT.NONE);
		TableColumn tblclmnGrammar = tbclvGrammar.getColumn();
		tblclmnGrammar.setWidth(100);
		tblclmnGrammar.setText("Grammar");

		TableViewerColumn tbclvVnMeaning = new TableViewerColumn(
				tblAntonymGrammars, SWT.NONE);
		TableColumn tblclmnVietnameseMeaning = tbclvVnMeaning.getColumn();
		tblclmnVietnameseMeaning.setWidth(100);
		tblclmnVietnameseMeaning.setText("Vietnamese meaning");
		CommonUtils.grammarsHookDoubleClickCommand(tblAntonymGrammars);

		// Specify column's width by a percentage
		TableColumnLayout tblColumnLayout = new TableColumnLayout();
		tblColumnLayout.setColumnData(tblclmnGrammar, new ColumnWeightData(35,
				true));
		tblColumnLayout.setColumnData(tblclmnVietnameseMeaning,
				new ColumnWeightData(60, true));
		compRelatedGrammar.setLayout(tblColumnLayout);

		initData();
		m_bindingContext = initDataBindings();
	}

	private void createToolBar(final Section section) {
		ToolBar toolbar = new ToolBar(section, SWT.FLAT);
		section.setTextClient(toolbar);

		ToolItem addItem = new ToolItem(toolbar, SWT.PUSH);
		addItem.setImage(Activator.getImageDescriptor("/icons/add.gif")
				.createImage());
		addItem.setToolTipText("Add a related Grammar to this Grammar");

		addItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				AddRelatedGrammarDialog relatedGrammarDialog = new AddRelatedGrammarDialog(
						section.getShell(), commonServices);
				if (relatedGrammarDialog.open() == Window.OK) {
					Set<Grammar> selectedGrammars = relatedGrammarDialog
							.getSelectedGrammars();
					if (!selectedGrammars.isEmpty()) {
						// update selected grammar as a related grammar
						// for current grammar
						grammar.getGrammarAntonyms().addAll(selectedGrammars);
						commonServices.getGrammarDao().merge(grammar);

						for (Grammar selectedGrammar : selectedGrammars) {
							// update current grammar as a related grammar of
							// selected grammar
							Grammar relatedGrammar = commonServices
									.getGrammarDao().getGrammarWithAntonyms(
											selectedGrammar.getGrammarId());
							relatedGrammar.getGrammarAntonyms().add(grammar);
							commonServices.getGrammarDao()
									.merge(relatedGrammar);
						}

						// add selected grammar to the Related vocabularies
						// table to display
						grammar.getGrammarAntonyms().addAll(selectedGrammars);

						m_bindingContext.updateModels();
						tblAntonymGrammars.refresh();
						tblAntonymGrammars.setSelection(new StructuredSelection(selectedGrammars.toArray()));
					}
				}
			}
		});

		ToolItem removeItem = new ToolItem(toolbar, SWT.PUSH);
		removeItem.setImage(Activator.getImageDescriptor("/icons/delete.gif")
				.createImage());
		removeItem
				.setToolTipText("Remove selected Category that this grammar belong to");

		removeItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection selection = (IStructuredSelection) tblAntonymGrammars
						.getSelection();
				Set<Grammar> selectedGrammars = CommonUtils
						.getSelectedGrammars(selection);
				if (!selectedGrammars.isEmpty()) {
					boolean confirm = MessageDialog.openConfirm(
							section.getShell(), "Deleting confirmation!",
							"Are you sure you want to delete this Grammar?");
					if (confirm) {
						// remove selected grammar as a related grammar
						// for
						// current grammar
						grammar.getGrammarAntonyms()
								.removeAll(selectedGrammars);
						commonServices.getGrammarDao().merge(grammar);

						for (Grammar selectedGrammar : selectedGrammars) {
							// remove current grammar as a related grammar of
							// selected grammar
							Grammar relatedGrammar = commonServices
									.getGrammarDao().getGrammarWithAntonyms(
											selectedGrammar.getGrammarId());
							relatedGrammar.getGrammarAntonyms().remove(grammar);
							commonServices.getGrammarDao()
									.merge(relatedGrammar);
						}

						// add selected grammar to the Related vocabularies
						// table to display
						grammar.getGrammarAntonyms()
								.removeAll(selectedGrammars);
					}

					m_bindingContext.updateModels();
					tblAntonymGrammars.refresh();
				}

			}
		});
	}

	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		ObservableSetContentProvider setContentProvider = new ObservableSetContentProvider();
		IObservableMap[] observeMaps = BeansObservables.observeMaps(
				setContentProvider.getKnownElements(), Grammar.class,
				new String[] { "grammar", "vnMeaning" });
		tblAntonymGrammars.setLabelProvider(new ObservableMapLabelProvider(
				observeMaps));
		tblAntonymGrammars.setContentProvider(setContentProvider);
		IObservableSet synonymVocabulariesSet = BeanProperties.set(
				"grammarAntonyms").observe(grammar);
		tblAntonymGrammars.setInput(synonymVocabulariesSet);
		//
		return bindingContext;
	}

}
